
package com.wyzz.hr.bo.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.FetchMode;
import org.hibernate.criterion.*;

import com.wyzz.hr.base.TreeNode;
import com.wyzz.hr.bo.IDepartmentBO;
import com.wyzz.hr.bo.IEmployeeBo;
import com.wyzz.hr.bo.IOuperfcriteriaBo;
import com.wyzz.hr.bo.IOuqualifyBo;
import com.wyzz.hr.bo.IOuresponseBo;
import com.wyzz.hr.bo.IPositionBaseBo;
import com.wyzz.hr.bo.IPositionBaseHistBo;
import com.wyzz.hr.bo.IPositionBo;
import com.wyzz.hr.bo.ISysLogBO;
import com.wyzz.hr.bo.OrgDeptOperateHelper;
import com.wyzz.hr.dao.IPositionBaseDao;
import com.wyzz.hr.pojo.Department;
import com.wyzz.hr.pojo.Ouperfcriteria;
import com.wyzz.hr.pojo.Ouqualify;
import com.wyzz.hr.pojo.Ouresponse;
import com.wyzz.hr.pojo.Position;
import com.wyzz.hr.pojo.PositionBase;
import com.wyzz.hr.pojo.PositionBaseHist;
import com.wyzz.hr.spring.SpringBeanFactory;
import com.wyzz.hr.util.DatabaseSysConfigManager;
import com.wyzz.hr.util.StringUtil;


public class PositionBaseBoImpl implements IPositionBaseBo {

	public PositionBaseBoImpl() {
		helper = new OrgDeptOperateHelper();
	}

	public IPositionBaseDao getPositionBaseDao() {
		return positionBaseDao;
	}

	public void setPositionBaseDao(IPositionBaseDao positionBaseDao) {
		this.positionBaseDao = positionBaseDao;
	}

	public List findAllActivePb() {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		dc
				.add(Restrictions.eq(PositionBase.PROP_PB_STATUS, Integer
						.valueOf(1)));
		dc.addOrder(Order.asc(PositionBase.PROP_PB_SORT_ID));
		return positionBaseDao.findByCriteria(dc);
	}

	public List findAllPbs() {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		dc.addOrder(Order.asc(PositionBase.PROP_PB_SORT_ID));
		return positionBaseDao.findByCriteria(dc);
	}

	public List findAllRespPb() {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		dc.add(Restrictions.eq(PositionBase.PROP_PB_IN_CHARGE, Integer
				.valueOf(1)));
		dc
				.add(Restrictions.eq(PositionBase.PROP_PB_STATUS, Integer
						.valueOf(1)));
		return positionBaseDao.findByCriteria(dc);
	}

	public List getActivePbsByDept(String deptId) {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		dc.setFetchMode(PositionBase.PROP_PB_DEPT_ID, FetchMode.JOIN);
		dc.setFetchMode(PositionBase.PROP_PB_SUP_ID, FetchMode.JOIN);
		dc
				.add(Restrictions.eq(PositionBase.PROP_PB_STATUS, Integer
						.valueOf(1)));
		dc.add(Restrictions.eq(PositionBase.PROP_PB_DEPT_ID, new Department(
				deptId)));
		dc.addOrder(Order.asc(PositionBase.PROP_PB_SORT_ID));
		return positionBaseDao.findByCriteria(dc);
	}

	public List getSupActivePbsByDept(String deptId) {
		IDepartmentBO deptBo = (IDepartmentBO) SpringBeanFactory
				.getBean("departmentBO");
		Department parentDept = deptBo.getDeptById(deptId)
				.getDepartmentParentId();
		if (parentDept == null)
			return null;
		else
			return getActivePbsByDept(parentDept.getId());
	}

	public PositionBase loadPb(Object id, String fetch[]) {
		return (PositionBase) positionBaseDao.loadObject(
				com.wyzz.hr.pojo.PositionBase.class, id, fetch,
				new boolean[] { false });
	}

	public List getAllPbsOfDept(String deptArr[]) {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		dc.setFetchMode(PositionBase.PROP_PB_JOB_TITLE, FetchMode.JOIN);
		dc.setFetchMode(PositionBase.PROP_PB_DEPT_ID, FetchMode.JOIN);
		dc.setFetchMode(PositionBase.PROP_PB_SUP_ID, FetchMode.JOIN);
		dc.add(Restrictions
				.in((new StringBuilder()).append(PositionBase.PROP_PB_DEPT_ID)
						.append(".id").toString(), deptArr));
		dc.addOrder(Order.asc(PositionBase.PROP_PB_SORT_ID));
		List pbList = positionBaseDao.findByCriteria(dc);
		return pbList;
	}

	public PositionBase getRespPBofDept(String deptId) {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		dc.createAlias(PositionBase.PROP_PB_SUP_ID, "pbSupId", 1);
		dc
				.add(Restrictions.eq((new StringBuilder()).append(
						PositionBase.PROP_PB_DEPT_ID).append(".id").toString(),
						deptId));
		dc.add(Restrictions.eq(PositionBase.PROP_PB_IN_CHARGE, new Integer(1)));
		List pbList = positionBaseDao.findByCriteria(dc);
		if (pbList.size() > 0)
			return (PositionBase) pbList.get(0);
		else
			return null;
	}

	public PositionBase getPBById(String pbId) {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		dc.setFetchMode(PositionBase.PROP_PB_DEPT_ID, FetchMode.JOIN);
		dc.add(Restrictions.eq(PositionBase.PROP_ID, pbId));
		List pbList = positionBaseDao.findByCriteria(dc);
		if (pbList.size() > 0)
			return (PositionBase) pbList.get(0);
		else
			return null;
	}

	public List getPbsOfDepts(List depts) {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		dc.add(Restrictions.in(PositionBase.PROP_PB_DEPT_ID, depts));
		dc.addOrder(Order.asc(PositionBase.PROP_PB_SORT_ID));
		List pbList = positionBaseDao.findByCriteria(dc);
		return pbList;
	}

	public synchronized Integer getMaxSortId() {
		String hql = "select max(pbSortId) from PositionBase";
		List maxNoList = positionBaseDao.exeHqlList(hql);
		Integer maxID;
		if (maxNoList == null || maxNoList.size() < 1
				|| maxNoList.get(0) == null)
			maxID = Integer.valueOf(1);
		else
			maxID = Integer.valueOf(1 + ((Integer) (Integer) maxNoList.get(0))
					.intValue());
		return maxID;
	}

	public synchronized Integer getNextPbSortIdOfDept(String deptId) {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		dc.add(Restrictions.eq(PositionBase.PROP_PB_DEPT_ID, new Department(
				deptId)));
		int count = positionBaseDao.findRowCountByCriteria(dc);
		count++;
		return Integer.valueOf(count);
	}

	public void saveOrupdatePb(PositionBase pb, String operatorNo) {
		String msgNewLog = "\u521B\u5EFA({0})\u804C\u4F4D\uFF0C\u7F16\u5236\u4E3A({1})\u4EBA\uFF01";
		String msgMaxEmpLog = "\u539F\u7F16\u5236({0})\u4EBA\uFF0C\u65B0\u7F16\u5236({1})\u4EBA\u3002";
		PositionBaseHist pbHist = null;
		PositionBaseHist latestPbHist = null;
		boolean isNew = false;
		if (StringUtils.isEmpty(pb.getId())) {
			isNew = true;
			initPbHist(pb, pbHist, latestPbHist);
		} else if (pb.getMaxEmpChanged().booleanValue())
			initPbHist(pb, pbHist, latestPbHist);
		positionBaseDao.saveOrupdate(pb);
		if (latestPbHist != null)
			positionBaseDao.saveOrupdate(latestPbHist);
		if (pbHist != null)
			positionBaseDao.saveOrupdate(pbHist);
		ISysLogBO logBO = (ISysLogBO) SpringBeanFactory.getBean("logBO");
		if (isNew) {
			msgNewLog = StringUtil.message(msgNewLog, new Object[] {
					pb.getPbName(), pb.getPbMaxEmployee() });
			logBO.addToSyslog("positionbase", operatorNo, null, pb.getId(), 0,
					"\u65B0\u5EFA", msgNewLog);
		} else if (pb.getMaxEmpChanged().booleanValue()) {
			msgMaxEmpLog = StringUtil.message(msgMaxEmpLog, new Object[] {
					pb.getHistMaxEmp(), pb.getPbMaxEmployee() });
			logBO.addToSyslog("positionbase", operatorNo, null, pb.getId(), 0,
					"\u66F4\u6539\u7F16\u5236", msgMaxEmpLog);
		}
	}

	private void initPbHist(PositionBase pb, PositionBaseHist pbHist,
			PositionBaseHist latestPbHist) {
		if (pb.getId() != null) {
			IPositionBaseHistBo pbHistBo = (IPositionBaseHistBo) SpringBeanFactory
					.getBean("positionBaseHistBo");
			latestPbHist = pbHistBo.getLatestPBHist(pb);
			if (latestPbHist != null)
				latestPbHist.setPbhiValidTo(new Date());
		}
		pbHist = new PositionBaseHist();
		pbHist.setPbhiDeptId(pb.getPbDeptId());
		pbHist.setPbhiInCharge(pb.getPbInCharge());
		pbHist.setPbhiMaxEmployee(pb.getPbMaxEmployee());
		pbHist.setPbhiPbId(pb);
		pbHist.setPbhiPbStatus(pb.getPbStatus());
		pbHist.setPbhiValidFrom(new Date());
	}

	public String startPb(String id) {
		PositionBase targetPb = (PositionBase) positionBaseDao.loadObject(
				com.wyzz.hr.pojo.PositionBase.class, id, null, new boolean[0]);
		if (targetPb == null || targetPb.getPbStatus().intValue() == 1) {
			return "\u72B6\u6001\u9519\u8BEF\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5\uFF01";
		} else {
			String info = helper.operateEnablePB(targetPb);
			return info;
		}
	}

	public String disablePb(String id) {
		PositionBase targetPb = (PositionBase) positionBaseDao.loadObject(
				com.wyzz.hr.pojo.PositionBase.class, id, null, new boolean[0]);
		if (targetPb == null || targetPb.getPbStatus().intValue() == 0) {
			return "\u72B6\u6001\u9519\u8BEF\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5\uFF01";
		} else {
			String info = helper.operateDisablePB(targetPb);
			return info;
		}
	}

	public boolean duplicateName(String id, String pbName, String deptId) {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		dc.add(Restrictions.eq(PositionBase.PROP_PB_DEPT_ID, new Department(
				deptId.trim())));
		dc.add(Restrictions.eq(PositionBase.PROP_PB_NAME, pbName.trim()));
		if (StringUtils.isNotEmpty(id))
			dc.add(Restrictions.not(Restrictions.eq(PositionBase.PROP_ID, id
					.trim())));
		List resultList = positionBaseDao.findByCriteria(dc);
		return resultList != null && resultList.size() != 0;
	}

	public boolean savePbOrder(String ids[]) {
		if (ids == null)
			return false;
		int sort = 1;
		int len = ids.length;
		for (int i = 0; i < len; i++) {
			positionBaseDao.exeHql((new StringBuilder()).append(
					"update PositionBase set pbSortId=").append(sort).append(
					" where id ='").append(ids[i]).append("'").toString());
			sort++;
		}

		return true;
	}

	public String delPb(String id) {
		PositionBase pb = loadPb(id, null);
		if (pb == null) {
			return "\u6570\u636E\u9519\u8BEF\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5\uFF01";
		} else {
			String info = helper.operateDeletePB(pb);
			return info;
		}
	}

	public List getSelectSubList(String posId) {
		Position pos = (Position) positionBaseDao.loadObject(
				com.wyzz.hr.pojo.Position.class, posId,
				new String[] { Position.PROP_POSITION_PB_ID }, new boolean[0]);
		if (pos != null) {
			PositionBase pb = pos.getPositionPbId();
			DetachedCriteria dc = DetachedCriteria
					.forClass(com.wyzz.hr.pojo.PositionBase.class);
			dc.setFetchMode(PositionBase.PROP_PB_DEPT_ID, FetchMode.JOIN);
			dc.add(Restrictions.eq(PositionBase.PROP_PB_IN_CHARGE, Integer
					.valueOf(0)));
			dc.add(Restrictions.eq(PositionBase.PROP_PB_DEPT_ID, pb
					.getPbDeptId()));
			dc.add(Restrictions.eq(PositionBase.PROP_PB_STATUS, Integer
					.valueOf(1)));
			dc.add(Restrictions.not(Restrictions.eq(PositionBase.PROP_ID, pb
					.getId())));
			List pbList = positionBaseDao.findByCriteria(dc);
			List supPbIds = getSupPBsOfPB(posId);
			Iterator pbItr = pbList.iterator();
			do {
				if (!pbItr.hasNext())
					break;
				PositionBase pbIn = (PositionBase) pbItr.next();
				if (supPbIds.contains(pbIn.getId()))
					pbItr.remove();
			} while (true);
			return pbList;
		}
		return null;
	}

	public List getSupPBsOfPB(String posId) {
		Position pos = (Position) positionBaseDao.loadObject(
				com.wyzz.hr.pojo.Position.class, posId,
				new String[] { Position.PROP_POSITION_PB_ID }, new boolean[0]);
		IPositionBo posBo = (IPositionBo) SpringBeanFactory
				.getBean("positionBo");
		List deptPosList = posBo.getPosListOfDept(pos.getPositionPbId()
				.getPbDeptId().getId());
		List parentPBIdsList = new ArrayList();
		Position currentPos = pos;
		boolean gotParent;
		do {
			if (currentPos == null)
				break;
			parentPBIdsList.add(currentPos.getPositionPbId().getId());
			String currentPosId;
			if (currentPos.getPositionParentId() == null)
				currentPosId = null;
			else
				currentPosId = currentPos.getPositionParentId().getId();
			gotParent = false;
			int i = 0;
			do {
				if (deptPosList == null || i >= deptPosList.size())
					break;
				Position tempPos = (Position) deptPosList.get(i);
				if (currentPosId != null
						&& currentPosId.equals(tempPos.getId())) {
					currentPos = tempPos;
					gotParent = true;
					break;
				}
				i++;
			} while (true);
		} while (gotParent);
		return parentPBIdsList;
	}

	public boolean checkPBExceed(PositionBase pb, int count) {
		String sysconfig = (String) DatabaseSysConfigManager.getInstance()
				.getProperties().get("sys.position.max.exceed");
		if (StringUtils.isEmpty(sysconfig))
			sysconfig = "0";
		int positionMaxExceed = Integer.parseInt(sysconfig);
		if (positionMaxExceed != 1)
			return false;
		if (pb.getPbInCharge().intValue() == 0
				&& (pb.getPbMaxExceed().intValue() == 0
						|| pb.getPbMaxExceed().intValue() == 2 || pb
						.getPbMaxEmployee() == null))
			return false;
		Long nowCount = new Long(0L);
		String hql = (new StringBuilder()).append(
				"select count(*) from Position where positionPbId.id='")
				.append(pb.getId())
				.append("' and positionEmpNo.id is not null").toString();
		List list = positionBaseDao.exeHqlList(hql);
		if (list != null && list.get(0) != null)
			nowCount = (Long) list.get(0);
		Integer maxEmployee = pb.getPbMaxEmployee();
		if (pb.getPbInCharge().intValue() == 1 && nowCount.longValue() > 0L)
			return true;
		return maxEmployee != null
				&& nowCount.intValue() + count > maxEmployee.intValue();
	}

	public Map getDeptPBMap(String deptIds[]) {
		DetachedCriteria dc = DetachedCriteria
				.forClass(com.wyzz.hr.pojo.PositionBase.class);
		if (deptIds != null && deptIds.length > 0)
			dc.add(Restrictions.in((new StringBuilder()).append(
					PositionBase.PROP_PB_DEPT_ID).append(".id").toString(),
					deptIds));
		List pbList = positionBaseDao.findByCriteria(dc);
		Map deptPBMap = new HashMap();
		for (int i = 0; i < pbList.size(); i++) {
			PositionBase pb = (PositionBase) pbList.get(i);
			List tempPBList = (List) deptPBMap.get(pb.getPbDeptId().getId());
			if (tempPBList == null) {
				tempPBList = new ArrayList();
				deptPBMap.put(pb.getPbDeptId().getId(), tempPBList);
			}
			tempPBList.add(pb);
		}

		return deptPBMap;
	}

	public void setPbOfNodeList(List depts, List nodeList, int status) {
		List pbList = getPbsOfDepts(depts);
		for (int i = 0; pbList != null && i < pbList.size(); i++) {
			PositionBase pb = (PositionBase) pbList.get(i);
			pb.setPbSupId(new PositionBase(pb.getPbDeptId().getId()));
			TreeNode node;
			if (pb.getPbStatus().intValue() == 1) {
				node = new TreeNode(pb.getId(), pb.getPbName(), pb.getPbSupId()
						.getId(), 3);
			} else {
				if (status == 0)
					continue;
				node = new TreeNode(pb.getId(), pb.getPbName(), pb.getPbSupId()
						.getId(), 4);
			}
			nodeList.add(i, node);
		}

	}

	public PositionBase copyPbToAnotherDept(String sourcePbId, String toDeptId,
			String operator) {
		PositionBase sourcePb = getPBById(sourcePbId);
		PositionBase newPb = new PositionBase();
		try {
			BeanUtils.copyProperties(newPb, sourcePb);
		} catch (IllegalAccessException e) {
			return null;
		} catch (InvocationTargetException e) {
			return null;
		}
		newPb.setId(null);
		newPb.setPbDeptId(new Department(toDeptId));
		newPb.setPbSupId(null);
		newPb.setPbInCharge(new Integer(0));
		if (duplicateName(null, newPb.getPbName(), toDeptId))
			newPb.setPbName((new StringBuilder()).append(sourcePb.getPbName())
					.append("(").append(
							sourcePb.getPbDeptId().getDepartmentName()).append(
							")").toString());
		saveOrupdatePb(newPb, operator);
		IOuresponseBo pbRespBo = (IOuresponseBo) SpringBeanFactory
				.getBean("ouresponseBo");
		List pbRespList = pbRespBo.getPbRespByPbId(sourcePbId);
		Ouresponse newResp;
		for (Iterator i$ = pbRespList.iterator(); i$.hasNext(); positionBaseDao
				.saveObject(newResp)) {
			Ouresponse pbResp = (Ouresponse) i$.next();
			newResp = new Ouresponse();
			newResp.setOurName(pbResp.getOurName());
			newResp.setOurRate(pbResp.getOurRate());
			newResp.setOurPb(newPb);
			newResp.setOurSortId(pbResp.getOurSortId());
		}

		IOuperfcriteriaBo perfcrBo = (IOuperfcriteriaBo) SpringBeanFactory
				.getBean("ouperfcriteriaBo");
		List pbPerfcrList = perfcrBo.getPbPerfcriteria(sourcePbId);
		Ouperfcriteria newPbPerfcr;
		for (Iterator i$ = pbPerfcrList.iterator(); i$.hasNext(); positionBaseDao
				.saveObject(newPbPerfcr)) {
			Ouperfcriteria pbPerfcr = (Ouperfcriteria) i$.next();
			newPbPerfcr = new Ouperfcriteria();
			newPbPerfcr.setOupName(pbPerfcr.getOupName());
			newPbPerfcr.setOupRate(pbPerfcr.getOupRate());
			newPbPerfcr.setOupSortId(pbPerfcr.getOupSortId());
			newPbPerfcr.setOupPb(newPb);
		}

		IOuqualifyBo pbQualifyBo = (IOuqualifyBo) SpringBeanFactory
				.getBean("ouqualifyBo");
		List pbQualifyList = pbQualifyBo.getpbQualifyByPbId(sourcePbId);
		Ouqualify newPbQualify;
		for (Iterator i$ = pbQualifyList.iterator(); i$.hasNext(); positionBaseDao
				.saveObject(newPbQualify)) {
			Ouqualify pbQualify = (Ouqualify) i$.next();
			newPbQualify = new Ouqualify();
			newPbQualify.setOuqName(pbQualify.getOuqName());
			newPbQualify.setOuqDesc(pbQualify.getOuqDesc());
			newPbQualify.setOuqPbId(newPb);
			newPbQualify.setOuqSortId(pbQualify.getOuqSortId());
		}

		return newPb;
	}

	public List findByCriteria(DetachedCriteria detachedCriteria) {
		List result = positionBaseDao.findByCriteria(detachedCriteria);
		if (result.isEmpty())
			return null;
		else
			return result;
	}

	public void setPBEmpInfo(PositionBase pb) {
		IEmployeeBo empBo = (IEmployeeBo) SpringBeanFactory.getBean("empBo");
		List empListByPb = empBo.getPbActiveEmpNos(pb.getId());
		int activeEmpNum = empListByPb.size();
		pb.setActiveEmpNum(Integer.valueOf(activeEmpNum));
		if (pb.getPbMaxEmployee() == null) {
			pb.setLackEmpNum(null);
		} else {
			int lackNum = pb.getPbMaxEmployee().intValue() - activeEmpNum;
			if (lackNum >= 0)
				pb.setLackEmpNum(Integer.valueOf(lackNum));
			else
				pb.setLackEmpNum(Integer.valueOf(0));
		}
	}

	private OrgDeptOperateHelper helper;
	private IPositionBaseDao positionBaseDao;
}
